package com.vmj.instructions.references;

import com.vmj.heap.*;
import com.vmj.heap.VMClass;
import com.vmj.instructions.base.Index16Instruction;
import com.vmj.rtda.Frame;
import com.vmj.rtda.OperandStack;

/**
 * Created by yangshoujun on 2017/8/27 下午12:00.
 */
public class GetStatic extends Index16Instruction {

    @Override
    public void execute(Frame frame) {
        RuntimeConstantPool cp = frame.getMethod().getClazz().getRuntimeConstantPool();
        FieldRef fieldRef = (FieldRef) cp.getConstant(getIndex()).getValue();
        Field field = fieldRef.resolvedField();
        VMClass clazz = field.getClazz();
        if(!clazz.isInitStarted()) {
            frame.revertNextPc();
            VMClass.initClass(frame.getThread(), clazz);
            return;
        }

        if(!field.isStatic()) {
            throw new RuntimeException("java.lang.IncompatibleClassChangeError");
        }

        String descriptor = field.getDescriptor();
        int slotId = field.getSlotId();
        OperandStack stack = frame.getOperandStack();
        Slots slots = clazz.getStaticVars();
        switch (descriptor.charAt(0)) {
            case 'Z':
            case 'B':
            case 'C':
            case 'S':
            case 'I':
                stack.pushInt(slots.getInt(slotId));
                break;
            case 'F':
                stack.pushFloat(slots.getFloat(slotId));
                break;
            case 'J':
                stack.pushLong(slots.getLong(slotId));
                break;
            case 'D':
                stack.pushDouble(slots.getDouble(slotId));
                break;
            case 'L':
            case '[':
                stack.pushRef(slots.getRef(slotId));
                break;
        }
    }
}
